"""
Market sentiment analysis service
"""

import asyncio
import aiohttp
from typing import Dict, List, Optional
from datetime import datetime, timedelta
import json
import re
from textblob import TextBlob
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer

from app.core.config import settings


class SentimentService:
    """Service for analyzing market sentiment from various sources"""
    
    def __init__(self):
        self.vader = SentimentIntensityAnalyzer()
        self.news_sources = [
            'coindesk',
            'cointelegraph',
            'cryptonews',
            'decrypt'
        ]
        
    async def get_sentiment_score(self, symbol: str) -> Dict[str, float]:
        """Get comprehensive sentiment score for a symbol"""
        
        # Get symbol name for searching
        symbol_name = self._get_symbol_name(symbol)
        
        # Collect sentiment from multiple sources
        twitter_sentiment = await self._analyze_twitter_sentiment(symbol_name)
        reddit_sentiment = await self._analyze_reddit_sentiment(symbol_name)
        news_sentiment = await self._analyze_news_sentiment(symbol_name)
        
        # Calculate weighted sentiment score
        weights = {
            'twitter': 0.4,
            'reddit': 0.3,
            'news': 0.3
        }
        
        weighted_score = (
            twitter_sentiment['score'] * weights['twitter'] +
            reddit_sentiment['score'] * weights['reddit'] +
            news_sentiment['score'] * weights['news']
        )
        
        return {
            'symbol': symbol,
            'score': weighted_score,
            'components': {
                'twitter': twitter_sentiment,
                'reddit': reddit_sentiment,
                'news': news_sentiment
            },
            'timestamp': datetime.now().isoformat()
        }
    
    def _get_symbol_name(self, symbol: str) -> str:
        """Convert trading symbol to search-friendly name"""
        symbol_map = {
            'BTC/USDT': 'bitcoin',
            'ETH/USDT': 'ethereum',
            'SOL/USDT': 'solana',
            'BNB/USDT': 'binance coin',
            'XRP/USDT': 'ripple',
            'ADA/USDT': 'cardano',
            'DOGE/USDT': 'dogecoin',
            'MATIC/USDT': 'polygon'
        }
        
        return symbol_map.get(symbol, symbol.replace('/USDT', '').lower())
    
    async def _analyze_twitter_sentiment(self, symbol: str) -> Dict[str, float]:
        """Analyze Twitter sentiment for symbol"""
        # This is a mock implementation
        # In production, use Twitter API v2
        
        # Mock data based on recent trends
        mock_scores = {
            'bitcoin': 0.65,
            'ethereum': 0.72,
            'solana': 0.58,
            'binance coin': 0.45,
            'ripple': 0.38,
            'cardano': 0.52,
            'dogecoin': 0.71,
            'polygon': 0.61
        }
        
        score = mock_scores.get(symbol, 0.5)
        
        return {
            'score': score,
            'volume': 1250,  # Number of tweets analyzed
            'positive': int(1250 * (score + 1) / 2),
            'negative': int(1250 * (1 - score) / 2),
            'source': 'twitter'
        }
    
    async def _analyze_reddit_sentiment(self, symbol: str) -> Dict[str, float]:
        """Analyze Reddit sentiment for symbol"""
        # Mock implementation
        # In production, use Reddit API
        
        mock_scores = {
            'bitcoin': 0.68,
            'ethereum': 0.75,
            'solana': 0.62,
            'binance coin': 0.48,
            'ripple': 0.42,
            'cardano': 0.55,
            'dogecoin': 0.73,
            'polygon': 0.64
        }
        
        score = mock_scores.get(symbol, 0.5)
        
        return {
            'score': score,
            'volume': 850,  # Number of Reddit posts/comments
            'positive': int(850 * (score + 1) / 2),
            'negative': int(850 * (1 - score) / 2),
            'source': 'reddit'
        }
    
    async def _analyze_news_sentiment(self, symbol: str) -> Dict[str, float]:
        """Analyze news sentiment for symbol"""
        # Mock implementation
        # In production, use news APIs
        
        mock_scores = {
            'bitcoin': 0.55,
            'ethereum': 0.62,
            'solana': 0.48,
            'binance coin': 0.52,
            'ripple': 0.35,
            'cardano': 0.58,
            'dogecoin': 0.45,
            'polygon': 0.59
        }
        
        score = mock_scores.get(symbol, 0.5)
        
        return {
            'score': score,
            'volume': 45,  # Number of news articles
            'positive': int(45 * (score + 1) / 2),
            'negative': int(45 * (1 - score) / 2),
            'source': 'news'
        }
    
    def analyze_text_sentiment(self, text: str) -> Dict[str, float]:
        """Analyze sentiment of a single text"""
        
        # Clean text
        text = self._clean_text(text)
        
        # VADER sentiment
        vader_scores = self.vader.polarity_scores(text)
        
        # TextBlob sentiment
        blob = TextBlob(text)
        textblob_score = blob.sentiment.polarity
        
        # Combine scores
        combined_score = (vader_scores['compound'] + textblob_score) / 2
        
        return {
            'score': combined_score,
            'confidence': vader_scores['compound'],
            'subjectivity': blob.sentiment.subjectivity
        }
    
    def _clean_text(self, text: str) -> str:
        """Clean and preprocess text for sentiment analysis"""
        # Remove URLs
        text = re.sub(r'http\S+|www.\S+', '', text)
        
        # Remove mentions and hashtags
        text = re.sub(r'@\w+|#\w+', '', text)
        
        # Remove special characters but keep spaces
        text = re.sub(r'[^\w\s]', '', text)
        
        # Convert to lowercase
        text = text.lower().strip()
        
        return text
    
    async def get_on_chain_metrics(self, symbol: str) -> Dict[str, float]:
        """Get on-chain metrics for sentiment analysis"""
        # Mock implementation
        # In production, use Glassnode, CryptoQuant, etc.
        
        symbol_map = {
            'BTC/USDT': {
                'exchange_inflow': 1250.5,
                'exchange_outflow': 980.3,
                'whale_transactions': 45,
                'active_addresses': 850000,
                'hash_rate': 150000000
            },
            'ETH/USDT': {
                'exchange_inflow': 8500.2,
                'exchange_outflow': 9200.8,
                'whale_transactions': 78,
                'active_addresses': 450000,
                'hash_rate': 250000
            }
        }
        
        return symbol_map.get(symbol, {
            'exchange_inflow': 0,
            'exchange_outflow': 0,
            'whale_transactions': 0,
            'active_addresses': 0,
            'hash_rate': 0
        })
    
    def calculate_fear_greed_index(self) -> Dict[str, float]:
        """Calculate crypto market fear & greed index"""
        # Mock implementation based on multiple factors
        
        factors = {
            'volatility': 0.65,
            'market_momentum': 0.72,
            'social_media': 0.58,
            'dominance': 0.68,
            'google_trends': 0.61
        }
        
        # Weighted average
        weights = {
            'volatility': 0.25,
            'market_momentum': 0.25,
            'social_media': 0.15,
            'dominance': 0.10,
            'google_trends': 0.25
        }
        
        index_value = sum(
            factors[key] * weights[key] 
            for key in factors.keys()
        ) * 100
        
        # Scale to 0-100
        fear_greed_index = max(0, min(100, index_value))
        
        sentiment_label = (
            "Extreme Fear" if fear_greed_index < 25 else
            "Fear" if fear_greed_index < 50 else
            "Neutral" if fear_greed_index < 75 else
            "Greed" if fear_greed_index < 90 else
            "Extreme Greed"
        )
        
        return {
            'index': fear_greed_index,
            'label': sentiment_label,
            'factors': factors,
            'timestamp': datetime.now().isoformat()
        }


# Global instance
sentiment_service = SentimentService()
